package main

import (
	"context"
	"flag"
	"gopkg.in/yaml.v2"
	"io"
	"lifi/config"
	_ "lifi/plugins/sinks/all"
	"lifi/plugins/sources"
	_ "lifi/plugins/sources/all"
	_ "lifi/plugins/transfers/all"
	"log"
	"os"
	"sync"
)

var (
	configFilePath string
	logFilePath    string
)

func init() {

	flag.StringVar(&configFilePath, "config", "config.yaml", "配置文件路径")
	flag.StringVar(&logFilePath, "log", "", "日志文件路径")
	flag.Parse()

}

func main() {

	configData, err := os.ReadFile(configFilePath)
	if err != nil {
		log.Fatalf("Exit! Cause cannot open Config file : %v", err)
	}
	// 初始化

	// 加载配置
	cfg := &config.Config{}
	err = loadConfig(cfg, configData)
	if err != nil || cfg.Pipelines == nil {
		log.Println("load config error:", err)
		os.Exit(1)
	}

	if logFilePath == "" {
		logFilePath = cfg.LogFilePath
	}
	// 打开日志文件以进行写入
	logFile, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		log.Printf("Error opening log file:%s,using stdout\n", err)
		logFile = os.Stdout
	}
	// 设置日志输出到文件
	log.SetOutput(logFile)
	defer func(logFile *os.File) {
		err := logFile.Close()
		if err != nil {
			log.Printf("Error closing log file:%s\n", err)
		}
	}(logFile)

	// 运行app

	err = RunPipes(os.Args[1:], os.Stdout, cfg)
	if err != nil {
		log.Println("run pipes error:", err)
		os.Exit(1)
	}
}

func RunPipes(args []string, stdout io.Writer, cfg *config.Config) error {
	var wg sync.WaitGroup

	for _, p := range cfg.Pipelines {
		log.Printf("start pipe:%v", p.Name)
		a := &Pipe{Pipeline: p}
		wg.Add(1)
		p := p
		go func() {
			defer wg.Done()
			err := RunApp(args, stdout, a)
			if err != nil {
				log.Printf("run pipe [%s] error:%v\n", p.Name, err)
			}
		}()

	}
	wg.Wait()
	return nil

}

func loadConfig(cfg *config.Config, data []byte) error {

	err := yaml.Unmarshal(data, cfg)
	if err != nil {
		log.Printf("Error file:%s\n", err)
	}
	log.Printf("using config:\n%v", string(data))

	return nil
}

// RunApp run app
func RunApp(args []string, buf io.Writer, a *Pipe) error {
	log.Printf("sourcs:%v", len(sources.Sources))
	err := a.RunPipeline(context.Background())
	if err != nil {
		log.Println("run app error:", err)
		return err
	}
	return nil
}
